﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Irony.Parsing;

namespace MudEngine.Parser
{
	public class CommandStringParser
	{
		public static string[] adjectives = new string[] { "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth" };
        public static string[] articles = new string[] { "the", "a", "an", "any", "my" };

		private CommandStringGrammar _grammar;

		public CommandStringParser(CommandStringGrammar grammar)
		{
            this._grammar = grammar;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public TToken[] ParseString(string str)
		{
            Irony.Parsing.Parser p = new Irony.Parsing.Parser(this._grammar);
			Irony.Parsing.ParseTree resultParseTree = p.Parse(str);
			TToken[] result = null;

			int i = 0;
			if (resultParseTree.Status == ParseTreeStatus.Error)
			{
				result = new TToken[resultParseTree.Tokens.Count];
				TToken t = new TToken();
				t.Type = TokenType.ERROR;
				t.Value = resultParseTree.ParserMessages[0].Message;

				result[i++] = t;
			}
			else
				result = new TToken[resultParseTree.Tokens.Count - 1];

			foreach (Token token in resultParseTree.Tokens)
			{
				if (i == result.Length)
					break;

				TToken tt = new TToken();
				if (token.Terminal is IdentifierTerminal)
				{
					tt.Type = (TokenType)Enum.Parse(typeof(TokenType), token.Terminal.Name);
					tt.Value = token.ValueString;

					if (i > 0 && result[i - 1].Type == tt.Type)
					{
						int idx = Array.IndexOf<string>(adjectives, result[i - 1].Value.ToString());
						if (idx > -1)
						{
							result[i - 1].Type = TokenType.NUMADJ;
							result[i - 1].Value = idx + 1;
						}
						else
							result[i - 1].Type = TokenType.ADJECTIVE;
					}
				}
				else if (token.Terminal is CustomTerminal)
				{
					tt.Type = TokenType.NUMADJ;
					tt.Value = token.Value;
				}
				else
				{
					tt.Type = TokenType.KEYWORD;
					tt.Value = token.ValueString;
				}
				result[i++] = tt;
			}
			Log.Debug(this.GetType(), string.Format("Command parsed as '{0}'", string.Join<TToken>(" ", result)));

			return result;
		}
	}

	public enum TokenType
	{
		OBJ,
		NUMADJ,
		ADJECTIVE,
		KEYWORD,
		ERROR
	}

	[Serializable]
	public class TToken
	{
		public TokenType Type { get; set; }
		public Object Value { get; set; }

		public override string ToString()
		{
			return Value.ToString() + "<" + Type + ">";
		}
	}
}
